﻿using System;
using System.Collections.Generic;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Xml;
using System.Xml.XPath;
using System.Net;

namespace CompendiumSearch
{
	public partial class CSMain : Form
	{
		public CSMain()
		{
			InitializeComponent();
		}

		private string baseServiceUrl = "http://www.wizards.com/dndinsider/compendium";
        private string stSearchType = "";
        private bool nameOnly = false;
        private XmlDocument filterItemsXml;
        private Dictionary<string, int> sources;
        private int currentSortCol = -1;

		private void lvResults_SelectedIndexChanged(object sender, EventArgs e)
		{
            if (lvResults.SelectedIndices.Count > 0)
            {
                // Update the web browser window with the content for the selected item
                string pwrID = ((ResultsListItem)lvResults.SelectedItems[0]).ri.ItemId;
                wbElementView.Navigate(baseServiceUrl + "/" + stSearchType + ".aspx?id=" + pwrID);
            }
		}

		private void CSMain_Load(object sender, EventArgs e)
		{

            lvResults.SelectedIndexChanged += new EventHandler(lvResults_SelectedIndexChanged);
            lvResults.ColumnClick += new ColumnClickEventHandler(lvColumnClicked);

            // retrieve the filter options from the web service
            string queryString = baseServiceUrl + "/compendiumsearch.asmx/GetFilterSelect";
            filterItemsXml = new XmlDocument();
            HttpWebRequest req = (HttpWebRequest)WebRequest.Create(queryString);
            WebResponse resp = req.GetResponse();
            filterItemsXml.Load(resp.GetResponseStream());

            // load various data from the filter options xml and initialize the controls
            PopulateSources();
            PopulateFilters();
		}

        /// <summary>
        /// Sorts the results based on the column clicked and the current sort order.
        /// </summary>
        /// <param name="o"></param>
        /// <param name="e"></param>
        private void lvColumnClicked(object o, ColumnClickEventArgs e)
        {
            if (currentSortCol == e.Column)
            {
                if (lvResults.Sorting == SortOrder.Ascending)
                {
                    lvResults.Sorting = SortOrder.Descending;
                    lvResults.ListViewItemSorter = new ListViewItemComparer(e.Column, false);
                }
                else
                {
                    lvResults.Sorting = SortOrder.Ascending;
                    lvResults.ListViewItemSorter = new ListViewItemComparer(e.Column, true);
                }
            }
            else
            {
                lvResults.Sorting = SortOrder.Ascending;
                lvResults.ListViewItemSorter = new ListViewItemComparer(e.Column, true);
            }
            currentSortCol = e.Column;
        }

        /// <summary>
        /// Submits a filtered keyword search to the compendium web service
        /// This is the workhors function of the program.  Each search type has its own
        /// logic for pulling data from the results.
        /// </summary>
        /// <param name="stKeywords">a string representing the keyword parameter for the ws call</param>
        /// <param name="stFilters">a string representing the filters paramter for the ws call</param>
		private void RunSearch(string stKeywords, string stFilters)
		{
            lvResults.Clear();
            lvResults.Sorting = SortOrder.None;
            lvResults.Columns.Add("Name", 150);
            string queryString = baseServiceUrl + "/compendiumsearch.asmx/KeywordSearchWithFilters?tab=" + stSearchType + "&NameOnly=" + 
                nameOnly.ToString() + "&Keywords=" + stKeywords + "&Filters=" + stFilters;

            XmlDocument returnXml = new XmlDocument();
            HttpWebRequest searchRequest = (HttpWebRequest)WebRequest.Create(queryString);
            try
            {
                WebResponse searchResponse = searchRequest.GetResponse();
                returnXml.Load(searchResponse.GetResponseStream());

                // parse results
                XPathNavigator xpn = returnXml.CreateNavigator();
                XPathNodeIterator iter = xpn.Select("//Data/Results/" + stSearchType);
                switch (stSearchType)
                {
                    case "Power":
                        {
                            lvResults.Columns.Add("Level", 50);
                            lvResults.Columns.Add("Class", 150);
                            lvResults.Columns.Add("Action", 150);
                            while (iter.MoveNext())
                            {
                                XPathNavigator nav = iter.Current.Clone();
                                ResultsItem itm = new ResultsItem(nav.SelectSingleNode(".//ID").InnerXml, nav.SelectSingleNode(".//Name").InnerXml);
                                itm.ItemLvl = nav.SelectSingleNode(".//Level").InnerXml;
                                itm.ItemType = nav.SelectSingleNode(".//ActionType").InnerXml;
                                itm.ItemClass = nav.SelectSingleNode(".//ClassName").InnerXml;
                                lvResults.Items.Add(new ResultsListItem(itm));
                            }
                            break;
                        }
                    case "Item":
                        {
                            lvResults.Columns.Add("Level", 50);
                            lvResults.Columns.Add("Slot", 150);
                            while (iter.MoveNext())
                            {
                                XPathNavigator nav = iter.Current.Clone();
                                ResultsItem itm = new ResultsItem(nav.SelectSingleNode(".//ID").InnerXml, nav.SelectSingleNode(".//Name").InnerXml);
                                itm.ItemLvl = nav.SelectSingleNode(".//Level").InnerXml;
                                itm.ItemType = nav.SelectSingleNode(".//Category").InnerXml;
                                lvResults.Items.Add(new ResultsListItem(itm));
                            }
                            break;
                        }
                    case "Monster":
                        {
                            lvResults.Columns.Add("Level", 50);
                            lvResults.Columns.Add("Main Role", 150);
                            lvResults.Columns.Add("Secondary Role", 200);
                            while (iter.MoveNext())
                            {
                                XPathNavigator nav = iter.Current.Clone();
                                ResultsItem itm = new ResultsItem(nav.SelectSingleNode(".//ID").InnerXml, nav.SelectSingleNode(".//Name").InnerXml);
                                itm.ItemLvl = nav.SelectSingleNode(".//Level").InnerXml;
                                itm.ItemType = nav.SelectSingleNode(".//GroupRole").InnerXml;
                                itm.ItemClass = nav.SelectSingleNode(".//CombatRole").InnerXml;
                                lvResults.Items.Add(new ResultsListItem(itm));
                            }
                            break;
                        }
                    case "Ritual":
                        {
                            lvResults.Columns.Add("Level", 50);
                            lvResults.Columns.Add("Key Skill", 200);
                            while (iter.MoveNext())
                            {
                                XPathNavigator nav = iter.Current.Clone();
                                ResultsItem itm = new ResultsItem(nav.SelectSingleNode(".//ID").InnerXml, nav.SelectSingleNode(".//Name").InnerXml);
                                itm.ItemLvl = nav.SelectSingleNode(".//Level").InnerXml;
                                itm.ItemType = nav.SelectSingleNode(".//KeySkillDescription").InnerXml;
                                lvResults.Items.Add(new ResultsListItem(itm));
                            }
                            break;
                        }
                    case "Feat":
                        {
                            lvResults.Columns.Add("Tier", 150);
                            while (iter.MoveNext())
                            {
                                XPathNavigator nav = iter.Current.Clone();
                                ResultsItem itm = new ResultsItem(nav.SelectSingleNode(".//ID").InnerXml, nav.SelectSingleNode(".//Name").InnerXml);
                                itm.ItemLvl = nav.SelectSingleNode(".//TierName").InnerXml;
                                lvResults.Items.Add(new ResultsListItem(itm));
                            }
                            break;
                        }
                    case "Trap":
                        {
                            lvResults.Columns.Add("Level", 50);
                            lvResults.Columns.Add("Role", 200);
                            while (iter.MoveNext())
                            {
                                XPathNavigator nav = iter.Current.Clone();
                                ResultsItem itm = new ResultsItem(nav.SelectSingleNode(".//ID").InnerXml, nav.SelectSingleNode(".//Name").InnerXml);
                                itm.ItemLvl = nav.SelectSingleNode(".//Level").InnerXml;
                                itm.ItemClass = nav.SelectSingleNode(".//GroupRole").InnerXml;
                                lvResults.Items.Add(new ResultsListItem(itm));
                            }
                            break;
                        }
                    case "Deity":
                        {
                            lvResults.Columns.Add("Allignment",200);
                            while (iter.MoveNext())
                            {
                                XPathNavigator nav = iter.Current.Clone();
                                ResultsItem itm = new ResultsItem(nav.SelectSingleNode(".//ID").InnerXml, nav.SelectSingleNode(".//Name").InnerXml);
                                itm.ItemType = nav.SelectSingleNode(".//Alignment").InnerXml;
                                lvResults.Items.Add(new ResultsListItem(itm));
                            }
                            break;
                        }
                    default:
                        {
                            while (iter.MoveNext())
                            {
                                XPathNavigator nav = iter.Current.Clone();
                                ResultsItem itm = new ResultsItem(nav.SelectSingleNode(".//ID").InnerXml, nav.SelectSingleNode(".//Name").InnerXml);
                                lvResults.Items.Add(new ResultsListItem(itm));
                            }
                            break;
                        }
                }
            }
            catch (Exception excep)
            {
                MessageBox.Show(excep.Message);
            }
        }

        #region StartupFunctions
        /// <summary>
        /// Populates all of the filter drop-downs with the supported options
        /// </summary>
        private void PopulateFilters()
        {
            // Powers tab
            PopulateFilterControl(ref comboPowerClass, "PowerClass");
            PopulateFilterControl(ref comboPowerKind, "PowerKind");
            PopulateFilterControl(ref comboPowerUsage, "PowerUsage");
            PopulateFilterControl(ref comboPowerType, "PowerActionType");
            PopulateFilterControl(ref comboPowerBook, "PowerSourceBook");
            PopulateFilterControl(ref comboPowerBook, "PowerSourceOther");

            // Monsters tab
            PopulateFilterControl(ref comboMonsterKeyword, "MonsterKeywords");
            PopulateFilterControl(ref comboMonsterSource, "MonsterSourceBook");
            PopulateFilterControl(ref comboMonsterSource, "MonsterSourceOther");

            // Items tab
            PopulateFilterControl(ref comboItemCat, "ItemSlot");
            PopulateFilterControl(ref comboItemSource, "ItemSourceBook");
            PopulateFilterControl(ref comboItemSource, "ItemSourceOther");

            // Glossary tab
            PopulateFilterControl(ref comboGlsCat, "GlossaryCategory");
            PopulateFilterControl(ref comboGlsType, "GlossaryType");
            PopulateFilterControl(ref comboGlsSource, "GlossarySourceBook");
            PopulateFilterControl(ref comboGlsSource, "GlossarySourceOther");

            // Feats tab
            PopulateFilterControl(ref comboFeatSource, "FeatSourceBook");
            PopulateFilterControl(ref comboFeatSource, "FeatSourceOther");

            // Rituals tab
            PopulateFilterControl(ref comboRitualSkill, "RitualKeySkill");
            PopulateFilterControl(ref comboRitualSource, "RitualSourceBook");
            PopulateFilterControl(ref comboRitualSource, "RitualSourceOther");

            // Paragon tab
            PopulateFilterControl(ref comboParagonClass, "ParagonClass");
            PopulateFilterControl(ref comboParagonRace, "PagaronRace");
            PopulateFilterControl(ref comboParagonSource, "ParagonSourceBook");
            PopulateFilterControl(ref comboParagonSource, "ParagonSourceOther");

            // Deity tab
            PopulateFilterControl(ref comboDeitySource, "DeitySourceBook");
            PopulateFilterControl(ref comboDeitySource, "DeitySourceOther");

            // Traps tab
            PopulateFilterControl(ref comboTrapMainRl, "TrapRole");
            PopulateFilterControl(ref comboTrapGroupRl, "TrapGroupRole");
            PopulateFilterControl(ref comboTrapSource, "TrapSourceBook");
            PopulateFilterControl(ref comboTrapSource, "TrapSourceOther");
            PopulateFilterControl(ref comboTrapType, "TrapType");

            // Race tab
            PopulateFilterControl(ref comboRaceSource, "RaceSourceBook");
            PopulateFilterControl(ref comboRaceSource, "RaceSourceOther");

            // Class tab
            PopulateFilterControl(ref comboClassSource, "ClassSourceBook");
            PopulateFilterControl(ref comboClassSource, "ClassSourceOther");

            // Epic tab
            PopulateFilterControl(ref comboEpicSource, "EpicSourceBook");
            PopulateFilterControl(ref comboEpicSource, "EpicSourceOther");
        }

        /// <summary>
        /// Populates the filter options for a single combobox control
        /// </summary>
        /// <param name="cb">reference to the control to populate</param>
        /// <param name="optionString">the string element identifier by which to search the filterselect xml</param>
        private void PopulateFilterControl(ref ComboBox cb, string optionString)
        {
            // select all of the matching nodes and insert into the control
            XPathNavigator xpn = filterItemsXml.CreateNavigator();
            XPathNodeIterator iter = xpn.Select("/Options/Option[type='"+ optionString +"']/val");
            while (iter.MoveNext())
            {
                string className = iter.Current.InnerXml;
                cb.Items.Add(className);
            }
        }

        private void PopulateSources()
        {
            sources = new Dictionary<string, int>();
            XPathNavigator xpn = filterItemsXml.CreateNavigator();
            XPathNodeIterator iter = xpn.Select("/Options/Option[contains(./type,'Source')]/val|/Options/Option[contains(./type,'Source')]/id");
            while (iter.MoveNext())
            {
                int id = Convert.ToInt32(iter.Current.InnerXml);
                iter.MoveNext();
                string val = iter.Current.InnerXml;
                if (sources.ContainsKey(val)) continue;
                sources.Add(val, id);
            }
        }
        #endregion

        #region SearchButtonHandlers

        private void btClass_Click(object sender, EventArgs e)
        {
            string filter = "";
            if (comboClassSource.SelectedItem == null) filter = "null";
            else filter = sources[comboClassSource.SelectedItem.ToString()].ToString();
            nameOnly = cbClassNameOnly.Checked;
            stSearchType = "Class";
            RunSearch(tbClass.Text, filter);
        }

        private void btDeitySearch_Click(object sender, EventArgs e)
        {
            string dtAlign, dtSource;
            if (comboDeityAlign.SelectedItem == null) dtAlign = "null";
            else dtAlign = comboDeityAlign.SelectedItem.ToString();
            if (comboDeitySource.SelectedItem == null) dtSource = "null";
            else dtSource = sources[comboDeitySource.SelectedItem.ToString()].ToString();
            string filter = string.Format("{0}|{1}", dtAlign, dtSource);
            nameOnly = cbDeityNameOnly.Checked;
            stSearchType = "Deity";
            RunSearch(tbDeity.Text, filter);
        }

        private void btEpicSearch_Click(object sender, EventArgs e)
        {
            string filter = "";
            if (comboEpicSource.SelectedItem == null) filter = "null";
            else filter = sources[comboEpicSource.SelectedItem.ToString()].ToString();
            nameOnly = cbEpicNameOnly.Checked;
            stSearchType = "EpicDestiny";
            RunSearch(tbEpic.Text, filter);
        }

        private void btFeatSearch_Click(object sender, EventArgs e)
        {
            string ftCat, ftSource;
            if (comboFeatCat.SelectedItem == null) ftCat = "null";
            else ftCat = comboFeatCat.SelectedItem.ToString();
            if (comboFeatSource.SelectedItem == null) ftSource = "null";
            else ftSource = sources[comboFeatSource.SelectedItem.ToString()].ToString();
            string filter = string.Format("{0}|{1}",ftCat,ftSource);
            nameOnly = cbFeatNameOnly.Checked;
            stSearchType = "Feat";
            RunSearch(tbFeat.Text, filter);
        }

        private void btGlossarySearch_Click(object sender, EventArgs e)
        {
            string glsCat, glsType, glsSource;
            if (comboGlsCat.SelectedItem == null) glsCat = "null";
            else glsCat = comboGlsCat.SelectedItem.ToString();
            if (comboGlsType.SelectedItem == null) glsType = "null";
            else glsType = comboGlsType.SelectedItem.ToString();
            if (comboGlsSource.SelectedItem == null) glsSource = "null";
            else glsSource = sources[comboGlsSource.SelectedItem.ToString()].ToString();
            string filter = string.Format("{0}|{1}|{2}", glsCat, glsType, glsSource);
            nameOnly = cbGlossaryNameOnly.Checked;
            stSearchType = "Glossary";
            RunSearch(tbGlossary.Text, filter);
        }

        private void btItemSearch_Click(object sender, EventArgs e)
        {
            string itCat, itSource, itMinLvl, itMaxLvl, itMinEnh, itMaxEnh, itMinCost, itMaxCost;
            if (comboItemCat.SelectedItem == null) itCat = "null";
            else itCat = comboItemCat.SelectedItem.ToString();
            if (comboItemSource.SelectedItem == null) itSource = "null";
            else itSource = sources[comboItemSource.SelectedItem.ToString()].ToString();
            if (tbItemMinLv.Text == "") itMinLvl = "-1";
            else itMinLvl = tbItemMinLv.Text;
            if (tbItemMaxLv.Text == "") itMaxLvl = "-1";
            else itMaxLvl = tbItemMaxLv.Text;
            if (tbItemMinEnh.Text == "") itMinEnh = "-1";
            else itMinEnh = tbItemMinEnh.Text;
            if (tbItemMaxEnh.Text == "") itMaxEnh = "-1";
            else itMaxEnh = tbItemMaxEnh.Text;
            if (tbItemMinCost.Text == "") itMinCost = "-1";
            else itMinCost = tbItemMinCost.Text;
            if (tbItemMaxCost.Text == "") itMaxCost = "-1";
            else itMaxCost = tbItemMaxCost.Text;
            string filter = string.Format("{0}|{1}|{2}|{3}|{4}|{5}|{6}|{7}", itCat, itMinLvl, itMaxLvl, itMinCost, itMaxCost, itMinEnh, itMaxEnh, itSource);
            nameOnly = cbItemNameOnly.Checked;
            stSearchType = "Item";
            RunSearch(tbItem.Text, filter);
        }

        private void btMonsterSearch_Click(object sender, EventArgs e)
        {
            string mnMain, mnGroup, mnSource, mnKeywords, mnMinLvl, mnMaxLvl, mnMinXp, mnMaxXp;
            if (comboMonsterMainRole.SelectedItem == null) mnMain = "null";
            else mnMain = comboMonsterMainRole.SelectedItem.ToString();
            if (comboMonsterGroupRole.SelectedItem == null) mnGroup = "null";
            else mnGroup = comboMonsterGroupRole.SelectedItem.ToString();
            if (comboMonsterSource.SelectedItem == null) mnSource = "null";
            else mnSource = sources[comboMonsterSource.SelectedItem.ToString()].ToString();
            if (comboMonsterKeyword.SelectedItem == null) mnKeywords = "null";
            else mnKeywords = comboMonsterKeyword.SelectedItem.ToString();
            if (tbMonsterMinLvl.Text == "") mnMinLvl = "1";
            else mnMinLvl = tbMonsterMinLvl.Text;
            if (tbPowerMaxLvl.Text == "") mnMaxLvl = "30";
            else mnMaxLvl = tbMonsterMaxLvl.Text;
            if (tbMonsterMinXp.Text == "") mnMinXp = "-1";
            else mnMinXp = tbMonsterMinXp.Text;
            if (tbMonsterMaxXp.Text == "") mnMaxXp = "-1";
            else mnMaxXp = tbMonsterMaxXp.Text;

            string filter = string.Format("{0}|{1}|{2}|{3}|{4}|{5}|{6}|{7}",
                mnMinLvl, mnMaxLvl, mnKeywords, mnGroup, mnMain, mnMinXp, mnMaxXp, mnSource);
            nameOnly = cbMonsterNameOnly.Checked;
            stSearchType = "Monster";
            RunSearch(tbMonster.Text, filter);
        }

        private void btParagonSearch_Click(object sender, EventArgs e)
        {
            string ppClass, ppRace, ppSource;
            if (comboParagonClass.SelectedItem == null) ppClass = "null";
            else ppClass = comboParagonClass.SelectedItem.ToString();
            if (comboParagonRace.SelectedItem == null) ppRace = "null";
            else ppRace = comboParagonRace.SelectedItem.ToString();
            if (comboParagonSource.SelectedItem == null) ppSource = "null";
            else ppSource = sources[comboParagonSource.SelectedItem.ToString()].ToString();
            string filter = string.Format("{0}|{1}|{2}", ppClass, ppRace, ppSource);
            nameOnly = cbParagonNameOnly.Checked;
            stSearchType = "ParagonPath";
            RunSearch(tbParagon.Text, filter);
        }

        private void btPowerSearch_Click(object sender, EventArgs e)
        {
            string pwType, pwClass, pwKind, pwMinLvl, pwMaxLvl, pwBook, pwUsage;
            if (comboPowerType.SelectedItem == null) pwType = "null";
            else pwType = comboPowerType.SelectedItem.ToString();
            if (comboPowerClass.SelectedItem == null) pwClass = "null";
            else pwClass = comboPowerClass.SelectedItem.ToString();
            if (comboPowerKind.SelectedItem == null) pwKind = "null";
            else pwKind = comboPowerKind.SelectedItem.ToString();
            if (tbPowerMinLvl.Text == "") pwMinLvl = "1";
            else pwMinLvl = tbPowerMinLvl.Text;
            if (tbPowerMaxLvl.Text == "") pwMaxLvl = "30";
            else pwMaxLvl = tbPowerMaxLvl.Text;
            if (comboPowerBook.SelectedItem == null) pwBook = "null";
            else pwBook = sources[comboPowerBook.SelectedItem.ToString()].ToString();
            if (comboPowerUsage.SelectedItem == null) pwUsage = "null";
            else pwUsage = comboPowerUsage.SelectedItem.ToString();
                            
            string filter = string.Format("{0}|{1}|{2}|{3}|{4}|{5}|{6}", 
                pwType, pwClass, pwKind, pwMinLvl, pwMaxLvl, pwBook, pwUsage);
            nameOnly = cbPowerNameOnly.Checked;
            stSearchType = "Power";
            RunSearch(tbPower.Text, filter);
        }

        private void btRaceSearch_Click(object sender, EventArgs e)
        {
            string filter = "";
            if (comboRaceSource.SelectedItem == null) filter = "null";
            else filter = sources[comboRaceSource.SelectedItem.ToString()].ToString();
            nameOnly = cbRaceNameOnly.Checked;
            stSearchType = "Race";
            RunSearch(tbRace.Text, filter);
        }

        private void btRitualSearch_Click(object sender, EventArgs e)
        {
            string rtSkill, rtSource, rtMinLvl, rtMaxLvl, rtMinCost, rtMaxCost;
            if (comboRitualSkill.SelectedItem == null) rtSkill = "null";
            else rtSkill = comboRitualSkill.SelectedItem.ToString();
            if (comboRitualSource.SelectedItem == null) rtSource = "null";
            else rtSource = sources[comboRitualSource.SelectedItem.ToString()].ToString();
            if (tbRitualMinLv.Text == "") rtMinLvl = "-1";
            else rtMinLvl = tbRitualMinLv.Text;
            if (tbRitualMaxLv.Text == "") rtMaxLvl = "-1";
            else rtMaxLvl = tbRitualMaxLv.Text;
            if (tbRitualMinPrc.Text == "") rtMinCost = "-1";
            else rtMinCost = tbRitualMinPrc.Text;
            if (tbRitualMaxPrc.Text == "") rtMaxCost = "-1";
            else rtMaxCost = tbRitualMaxPrc.Text;
            string filter = string.Format("{0}|{1}|{2}|{3}|{4}|{5}", rtMinLvl,rtMaxLvl,rtSkill,rtMinCost,rtMaxCost,rtSource);
            nameOnly = cbRitualNameOnly.Checked;
            stSearchType = "Ritual";
            RunSearch(tbRitual.Text, filter);
        }

        private void btSkillSearch_Click(object sender, EventArgs e)
        {
            if (tbSkill.Text == "")
            {
                lvResults.Clear();
                lvResults.Sorting = SortOrder.None;
                lvResults.Columns.Add("Name", 150);
                stSearchType = "Skill";
                string queryString = baseServiceUrl + "/compendiumsearch.asmx/ViewAll?tab=Skill";

                XmlDocument returnXml = new XmlDocument();
                HttpWebRequest searchRequest = (HttpWebRequest)WebRequest.Create(queryString);
                try
                {
                    WebResponse searchResponse = searchRequest.GetResponse();
                    returnXml.Load(searchResponse.GetResponseStream());

                    // parse results
                    XPathNavigator xpn = returnXml.CreateNavigator();
                    XPathNodeIterator iter = xpn.Select("//Data/Results/Skill");
                    while (iter.MoveNext())
                    {
                        string pwrName = "", pwrID = "";
                        XPathNavigator nav = iter.Current.Clone();
                        pwrName = nav.SelectSingleNode(".//Name").InnerXml;
                        pwrID = nav.SelectSingleNode(".//ID").InnerXml;
                        ResultsItem itm = new ResultsItem(pwrID, pwrName);
                        lvResults.Items.Add(new ResultsListItem(itm));
                    }
                }
                catch (Exception excep)
                {
                    MessageBox.Show(excep.Message);
                }

            }
            else
            {
                nameOnly = cbSkillNameOnly.Checked;
                RunSearch(tbSkill.Text, "");
            }
        }

        private void btTrapSearch_Click(object sender, EventArgs e)
        {
            string trpMainRl, trpGroupRl, trpType, trpSource, trpMinLvl, trpMaxLvl;
            if (comboTrapMainRl.SelectedItem == null) trpMainRl = "null";
            else trpMainRl = comboTrapMainRl.SelectedItem.ToString();
            if (comboTrapGroupRl.SelectedItem == null) trpGroupRl = "null";
            else trpGroupRl = comboTrapGroupRl.SelectedItem.ToString();
            if (comboTrapSource.SelectedItem == null) trpSource = "null";
            else trpSource = sources[comboTrapSource.SelectedItem.ToString()].ToString();
            if (comboTrapType.SelectedItem == null) trpType = "null";
            else trpType = comboTrapType.SelectedItem.ToString();
            if (tbTrapMinLv.Text == "") trpMinLvl = "-1";
            else trpMinLvl = tbTrapMinLv.Text;
            if (tbTrapMaxLv.Text == "") trpMaxLvl = "-1";
            else trpMaxLvl = tbTrapMaxLv.Text;
            string filter = string.Format("{0}|{1}|{2}|{3}|{4}|{5}", trpMinLvl,trpMaxLvl,trpMainRl,trpGroupRl,trpType,trpSource);
            nameOnly = cbTrapNameOnly.Checked;
            stSearchType = "Trap";
            RunSearch(tbTrap.Text, filter);
        }

        #endregion
    }

    class ResultsListItem : ListViewItem
    {
        public ResultsItem ri;

        public ResultsListItem (ResultsItem it)
        {
            ri = it;
            this.Text = ri.ItemName;
            if (ri.ItemLvl != null)
                this.SubItems.Add(ri.ItemLvl);
            if (ri.ItemClass != null)
                this.SubItems.Add(ri.ItemClass);
            if (ri.ItemType != null)
                this.SubItems.Add(ri.ItemType);
        }
    }

    class ListViewItemComparer : IComparer
    {
        private int col;
        private bool asc;

        public ListViewItemComparer()
        {
            col = 0;
        }
        public ListViewItemComparer(int column, bool ascending)
        {
            col = column;
            asc = ascending;
        }
        public int Compare(object x, object y)
        {
            string str1 = ((ListViewItem)x).SubItems[col].Text;
            string str2 = ((ListViewItem)y).SubItems[col].Text;
            int int1=0,int2=0;
            if (int.TryParse(str1, out int1))
            {
                int.TryParse(str2, out int2);
                if (asc)
                    return (int1 - int2);
                else
                    return (int2 - int1);
            }
            else
            {
                int compVal = String.Compare(str1, str2);
                if (asc)
                {
                    return compVal;
                }
                else
                {
                    return -compVal;
                }
            }
        }
    }
}
